//----------------------------------------------------------------------------------------------
//	Filename:	GraphCut.h
//	Author:		Sandro Spina
//	Date:		27/01/2013
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------

#include "GraphCut.h"
#include <boost\lexical_cast.hpp>

using namespace Illumina::Core;

GraphCut::GraphCut(std::string &pLabel)
{						
	label = pLabel;
	id = new ::UniqueID();
	DirectionsTravelled = new std::map<std::string, int>();		
	cutNodes = new std::map<int, StructureGraph::Node *>();
	orderedCutNodes = new std::vector<int>();
	score = -1;
	transitionCount = 0;
}

void GraphCut::AddNode(StructureGraph::Node * pNode)
{
	(*cutNodes)[pNode->id] = pNode;
}

void GraphCut::Clear() 
{
	cutNodes->clear();
	DirectionsTravelled->clear();	
}

void GraphCut::ExecuteActions(std::vector<ObjStructureGraph::action> actions, StructureGraph::Node * p_source,
																				StructureGraph::Node * p_sink)
{
	//Execute Actions ....
	for (std::vector<ObjStructureGraph::action>::iterator actionsiterator = actions.begin(); actionsiterator != actions.end(); actionsiterator++)
	{		
		switch (*actionsiterator)
		{
			case ObjStructureGraph::action::transition_count:
			{
				transitionCount+=1;
				//std::cout << p_source->id << "-" << p_sink->id << " #TrCount=" << transitionCount << std::endl; 
				break;
			}

			case ObjStructureGraph::action::add_direction:
			{
				//compute direction from median point in source to median point in sink
				int mask_x = 0;
				int mask_y = 0;
				int mask_z = 0;

				p_source->stats->mean_bounding_volume.X > p_sink->stats->mean_bounding_volume.X ?  mask_x = 1 : mask_x = 0;
				p_source->stats->mean_bounding_volume.Y > p_sink->stats->mean_bounding_volume.Y ?  mask_y = 1 : mask_y = 0;
				p_source->stats->mean_bounding_volume.Z > p_sink->stats->mean_bounding_volume.Z ?  mask_z = 1 : mask_z = 0;

				std::string mask = boost::lexical_cast<std::string>(mask_x) + boost::lexical_cast<std::string>(mask_y) + boost::lexical_cast<std::string>(mask_z);
				if (DirectionsTravelled->find(mask) != DirectionsTravelled->end())
				{
					DirectionsTravelled->at(mask)+=1;
					//std::cout << p_source->id << "-" << p_sink->id << " #IncDir[" << mask << "] to " << DirectionsTravelled->at(mask) << std::endl; 
				}
				else
				{
					(*DirectionsTravelled)[mask] = 1;
					//std::cout << p_source->id << "-" << p_sink->id << " #NewDir[" << mask << "] to " << DirectionsTravelled->at(mask) << std::endl; 
				}
				
				break;
			}

		}
	}
	//...and clear vector
	//actions->clear();
}

void GraphCut::ExecuteActionsFromTrace(std::vector<ObjStructureGraph::Node*> pObjTrace, 
									   std::vector<int> * pSceneTrace, std::vector<int> * pEdgeIds)
{	
	ObjStructureGraph::Node * objSource = pObjTrace.front();	
	ObjStructureGraph::Node * objSink;
	
	std::vector<int>::iterator sceneTraceIterator = pSceneTrace->begin();
	std::vector<int>::iterator edgeIdsIterator = pEdgeIds->begin();
	
	int sceneSource = *sceneTraceIterator; sceneTraceIterator++;
	int edgeIdx = *edgeIdsIterator; edgeIdsIterator++;

	int sceneSink;
	
	for (std::vector<ObjStructureGraph::Node*>::iterator objtraceiterator = pObjTrace.begin()+1; objtraceiterator != pObjTrace.end(); 
		objtraceiterator++, sceneTraceIterator++, edgeIdsIterator++)
	{
		objSink = (*objtraceiterator);
		sceneSink = (*sceneTraceIterator);
		edgeIdx = (*edgeIdsIterator);
		ExecuteActions(objSource->edges->at(edgeIdx)->first->actions, cutNodes->at(sceneSource), cutNodes->at(sceneSink));
		//switch next sources with current sinks
		objSource = objSink;
		sceneSource = sceneSink;
	}

	//TODO Deallocate memory allocated in the nodes ... IMPORTANT BIG MEMORY LEAK HERE
	//pObjTrace->clear();	
}
	
GraphCutSet::GraphCutSet()
{						
	id = new ::UniqueID();		
	sets = new std::vector<GraphCut>();
}	